// ==============================================================================================================
// ==============================================================================================================
// =========================================         数组         ================================================
// ==============================================================================================================
// ==============================================================================================================

/**
 *  数组分割：
 *  将数据按照n等分的分割
 *  @list {Array} 被分割的目标
 *  @chunkSize {Number} 按照几等分的分割。小于1则返回空数组
 *  @return {Array} 返回一个二维数组，第二维是被分割的部分
 **/
const listChunk = (list = [], chunkSize = 1) => {
    const result = [],
        tmp = [...list];
    if (!Array.isArray(list) || !Number.isInteger(chunkSize) || chunkSize <= 0) return result;
    while (tmp.length) result.push(tmp.splice(0, chunkSize));
    return result;
};

/**
 * 求数组元素交集:
 * 比较两个数组是否有交集，有则返回交集，无则返回第一个参数的数组。注意：该方法只能比较基础数据类型，如果不是基础数据类型，则会空数组。
 * @firstList {Array} 
 * @args {Array*} 如果有多个数组的话，则只有当firstList和...args全部存在交集时，才能返回有交集的结果
 * @return {Array} 返回一个包含交集的数组
 **/
const listIntersection = (firstList, ...args) => {
    if (!Array.isArray(firstList) || !args.length) return firstList;
    return firstList.filter(item => args.every(list => list.includes(item)));
};

/**
 * 按下标重新组合数组:
 * 将多个数组按照下标来提取数据并组合成一个新的数组。
 * @firstList {Array} 
 * @args {Array*} 
 * @return {Array} 例子： zip(['a', 'b'], [1, 2], [true, false]); ==> [["a", 1, true],["b", 2, false]]
 **/
const zip = (firstList, ...args) => {
    if (!Array.isArray(firstList) || !args.length) return firstList;
    return firstList.map((value, index) => {
        const newArgs = args.map(arg => arg[index]).filter(arg => arg !== undefined);
        return [value, ...newArgs];
    });
};

/**
 * 按下标组合数组为对象：
 * 将多个数组按照下标来提取数据并组合成一个新的对象。
 * @keys {Array}
 * @values {Array}
 *  @return {Object}
 **/
const zipObject = (keys, values = {}) => {
    if (!Array.isArray(keys)) return {};
    return keys.reduce((acc, cur, index) => {
        acc[cur] = values[index];
        return acc;
    }, Object.create({}));
};


/**
 * 检查对象属性的值:
 * 
 **/
const checkValue = (obj = {}, objRule = {}) => {
    const isObject = obj => {
        return Object.prototype.toString.call(obj) === '[object Object]';
    };
    if (!isObject(obj) || !isObject(objRule)) {
        return false;
    }
    return Object.keys(objRule).every(key => objRule[key](obj[key]));
};

const object = {
    a: 1,
    b: 2
};

checkValue(object, {
    b: n => n > 1,
})
// true

checkValue(object, {
    b: n => n > 2,
})
// false

// ==============================================================================================================
// ==============================================================================================================
// =========================================         字符串       ================================================
// ==============================================================================================================
// ==============================================================================================================

/**
 * 因es6之前不能使用模板字符串,该方法模拟模板字符串，支持算术运算、逻辑运算等运算。
 * @templateString {String} 类似模拟模板字符串，不过不是使用（破折号`）来作为模拟模板字符串了，而是使用正常的字符串，其中要被替换的部分使用双花括号括起来。例如 "<p>{{name + 123}},{{id.id}},{{id.id.xxx}}</p>"
 * @templateDataObject {Object} 替换字符串中的对应的数据。可选（可选时要求方法之外有字符串中的对应的数据）。例如：{name: '测试', id:{id:{xxx:"xxx"}}}
 * @template {Boolean} 字符串模板的模板样式。默认的模板样式是使用 {{}}双花括号括起来, 当设置true是，将使用es6的模板字符串的模板样式，即是 ${}  括起来。
 **/
function templateString(templateString, templateDataObject, template) {
    var reg = template ? /\$\{(.+?)\}/g : /\{\{(.+?)\}\}/g;
    var isNull = template ? /\$\{(\s*?)\}/g : /{{\s*?}}/;
    try {
        if (isNull.test(templateString)) throw ("存在空白字符模板:" + isNull.exec(templateString) + " => " + templateString);
        if (templateDataObject) {
            var _var = '';
            Object.keys(templateDataObject).filter(function (item) {
                _var += 'var ' + item + "=" + JSON.stringify(templateDataObject[item]) + ";";
            })
            eval(_var);
        }
        // 判断是否是IE 11及以下或者其他(其他里包括IE edge)
        if (!window.ActiveXObject || !("ActiveXObject" in window)) {
            return eval('`' + templateString + '`')
        }
        return templateString.replace(reg, function (match, $1) {
            //使用强大的eval函数直接将字符串按变量执行
            return eval($1.trim());
        });
    } catch (e) {
        console.error(e.message ? e.message + ' => ' + templateString : e);
        return '';
    }
}